package dao.impl;

import dao.TaskDAO;
import domain.Root;
import domain.Task;
import util.DateComparator;

import javax.xml.bind.*;
import java.io.*;
import java.util.*;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.XMLFormatter;

/**
 * User: Алексей
 * Date: 10.11.12
 * Time: 13:10
 */
public class TaskDAOImpl implements TaskDAO {

    private Marshaller marshaller;
    private Root root;
    private static java.util.logging.Logger log = java.util.logging.Logger.getLogger(TaskDAOImpl.class.getName());
    private String fileName;

    public TaskDAOImpl(String fileName) {
        this.fileName = fileName;
        try {
            FileHandler fileHandler = new FileHandler("dao.xml");
            fileHandler.setFormatter(new XMLFormatter());
            log.addHandler(fileHandler);
            log.setLevel(Level.FINE);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            JAXBContext context = JAXBContext.newInstance(Root.class);
            Unmarshaller u = context.createUnmarshaller();
            marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            root = (Root) u.unmarshal(new FileInputStream(fileName));
            Collections.sort(root.getTasks(), new DateComparator());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<Task> getAllTasks() {
        return root.getTasks();
    }

    @Override
    public Task getTask(int id) {
        for (Task task : root.getTasks()) {
            if (task.getId() == id) return task;
        }
        return null;
    }

    @Override
    public void add(Task task) {
        task.setId(incrementId());
        root.getTasks().add(task);
        updateXML();
        //log.fine(String.format("Task %s added", task.getName()));
    }

    @Override
    public void update(int id, Task task) {
        int i = 0;
        for (Task oldTask : root.getTasks()) {
            if (oldTask.getId() == id) {
                root.getTasks().remove(i);
                root.getTasks().add(task);
                updateXML();
                //log.fine(String.format("Task %s updated", task.getName()));
                break;
            }
            i++;
        }
    }

    @Override
    public void delete(int id) {
        int i = 0;
        for (Task oldTask : root.getTasks()) {
            if (oldTask.getId() == id) {
                root.getTasks().remove(i);
                updateXML();
                //log.fine(String.format("Task %s deleted", oldTask.getName()));
                break;
            }
            i++;
        }
    }

    @Override
    public void refresh() {
        try {
            JAXBContext context = JAXBContext.newInstance(Root.class);
            Unmarshaller u = context.createUnmarshaller();
            root = (Root) u.unmarshal(new FileInputStream(fileName));
            Collections.sort(root.getTasks(), new DateComparator());
        } catch (JAXBException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (FileNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    @Override
    public Task getTaskFromStorage(int id) {
        try {
            JAXBContext context = JAXBContext.newInstance(Root.class);
            Unmarshaller u = context.createUnmarshaller();
            Root root = (Root) u.unmarshal(new FileInputStream(fileName));
            for (Task task : root.getTasks()) {
                if (task.getId() == id) return task;
            }
        } catch (JAXBException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (FileNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return null;
    }

    private void updateXML() {
        try {
            marshaller.marshal(root, new FileOutputStream(fileName));
        } catch (JAXBException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private synchronized int incrementId() {
        int id = 0;
        try {
            Scanner in = new Scanner(new FileReader("id.txt"));
            id = in.nextInt() + 1;
            PrintWriter out = new PrintWriter(new FileWriter("id.txt"));
            out.print(id);
            in.close();
            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return id;
    }
}
